import axios, {
  AxiosRequestConfig,
  AxiosResponse,
  CancelTokenSource,
} from "axios";

// 存储请求标识和对应的取消函数
const pendingRequests = new Map<string, CancelTokenSource>();

// 定义基础响应接口
interface BaseResponse<T = any> {
  code: number;
  data: T;
  message: string;
  success: boolean;
}

class HttpService {
  // 创建axios实例
  private instance = axios.create({
    baseURL: import.meta.env.VITE_API_BASE_URL || "/api",
    timeout: 10000,
    headers: {
      "Content-Type": "application/json",
    },
  });

  constructor() {
    this.setupInterceptors();
  }

  private setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // 添加token到请求头
        const token = localStorage.getItem("auth_token");
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }

        // 处理取消请求
        if (config.cancelToken) {
          const source = axios.CancelToken.source();
          config.cancelToken = source.token;

          if (config.url && typeof config.url === "string") {
            const requestId = config.url;
            pendingRequests.set(requestId, source);
          }
        }

        return config;
      },
      (error) => Promise.reject(error)
    );

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response) => response,
      (error) => {
        if (error.response) {
          const { status } = error.response;

          // 处理常见HTTP错误
          switch (status) {
            case 401:
              // 未授权，清除token并重定向到登录页
              localStorage.removeItem("auth_token");
              // 可以在这里添加重定向逻辑
              break;
            case 403:
              // 权限不足
              console.error("没有权限访问此资源");
              break;
            case 404:
              // 资源不存在
              console.error("请求的资源不存在");
              break;
            case 500:
              // 服务器错误
              console.error("服务器错误");
              break;
            default:
              console.error(`HTTP错误: ${status}`);
          }
        } else if (axios.isCancel(error)) {
          // 请求被取消
          console.log("请求已取消:", error.message);
        } else {
          // 其他错误
          console.error("请求错误:", error.message);
        }

        return Promise.reject(error);
      }
    );
  }

  // 通用请求方法
  public async request<T = any>(
    config: AxiosRequestConfig
  ): Promise<AxiosResponse<BaseResponse<T>>> {
    return this.instance.request(config);
  }

  // GET请求
  public async get<T = any>(
    url: string,
    params?: any,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<BaseResponse<T>>> {
    return this.instance.get(url, { params, ...config });
  }

  // POST请求
  public async post<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<BaseResponse<T>>> {
    return this.instance.post(url, data, config);
  }

  // PUT请求
  public async put<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<BaseResponse<T>>> {
    return this.instance.put(url, data, config);
  }

  // DELETE请求
  public async delete<T = any>(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<AxiosResponse<BaseResponse<T>>> {
    return this.instance.delete(url, config);
  }

  // 下载附件
  public async download(
    url: string,
    params?: any,
    config?: AxiosRequestConfig
  ): Promise<void> {
    const response = await this.instance.get(url, {
      params,
      responseType: "blob", // 设置响应类型为blob
      ...config,
    });

    // 创建下载链接并触发下载
    const blob = new Blob([response.data]);
    const downloadUrl = window.URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = downloadUrl;

    // 从响应头中获取文件名
    const contentDisposition = response.headers["content-disposition"];
    const fileName = contentDisposition
      ? decodeURIComponent(
          contentDisposition.split("filename=")[1]?.replace(/"/g, "") || "file"
        )
      : "file";

    link.download = fileName;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(downloadUrl);
  }

  // 取消请求
  public cancelRequest(requestId: string): void {
    const source = pendingRequests.get(requestId);
    if (source) {
      source.cancel(`请求 ${requestId} 已被取消`);
      pendingRequests.delete(requestId);
    }
  }

  // 取消所有请求
  public cancelAllRequests(): void {
    pendingRequests.forEach((source) => {
      source.cancel("所有请求已被取消");
    });
    pendingRequests.clear();
  }
}

const http = new HttpService();
export default http;
